package thulearningcore;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import thulearningcore.util.ActionListener;
import thulearningcore.util.DESCrypto;
import thulearningcore.util.TLCookieManager;
import thulearningcore.util.TLExceptionEvent;

public class LearningManager {
	private static LearningManager instance = null;
	private static String suffix = "conf";
	private static String baseAddress = "http://learn.syx.thcic.cn";//"http://learn.tsinghua.edu.cn";

	private LoginManager account;
	private DataManager data;
	private ConnectionExceptionManager connEx;

	/**
	 * Default Constructor
	 */
	private LearningManager() {
		account = new LoginManager(null, null);
		data = new DataManager();
		connEx = new ConnectionExceptionManager();
	}

	/**
	 * @return singleton instance
	 */
	public static LearningManager getInstance() {
		if (instance == null) {
			instance = new LearningManager();
		}
		return instance;
	}

	/**
	 * @param username
	 *            : username
	 * @param password
	 *            : password
	 * @return: manager with new account
	 */
	public static LearningManager setAccount(String username, String password) {
		LearningManager.getInstance().setUserid(username);
		LearningManager.getInstance().setUserpass(password);
		LearningManager.getInstance().clearData();
		LearningManager.getInstance().getConnectionExceptionManager().clearAllListeners();
		return LearningManager.getInstance();
	}

	public static LearningManager clearAccount() {
		LearningManager.setAccount(null, null);
		TLCookieManager.getInstance().clearCookie();
		return LearningManager.getInstance();
	}
	
	public static boolean performExceptionEvent(TLExceptionEvent e) {
		LearningManager.getInstance().getConnectionExceptionManager().performEvent(e);
		return e.getException() != TLExceptionEvent.UNKNOWN_EXCEPTION;
	}
	
	public ConnectionExceptionManager getConnectionExceptionManager() {
		return connEx;
	}

	public void addListener(ActionListener listener) {
		this.data.addListener(listener);
	}

	public void removeListener(ActionListener listener) {
		this.data.removeListener(listener);
	}
	
	public void setUserid(String id) {
		account.setUserid(id);
		this.clearData();
	}

	public void setUserpass(String pass) {
		account.setUserpass(pass);
	}

	public String getUserId() {
		return account.getUserid();
	}

	public String getUserpass() {
		return account.getUserpass();
	}

	public DataManager getData() {
		return data;
	}

	public void setData(DataManager data) {
		this.data = data;
	}
	
	public static String getBaseAddress() {
		return baseAddress;
	}

	public void loadAllData(boolean withCourseList,boolean withDetail) {
		if (withDetail)
			this.data.loadAllData(withCourseList);
		else
			this.data.loadAllList(withCourseList);
	}

	public void updateData() {
		this.data.updateData();
	}

	/**
	 * Clear all data in this manager.
	 */
	public void clearData() {
		this.data = new DataManager();
	}

	/**
	 * Login with current account
	 * 
	 * @return 0 if login is succeeded,or errorcode if failed.
	 */
	synchronized public int login() {
		return account.login();
	}

	synchronized public boolean writeDataToFile(String path) {
		File file;
		DataOutputStream dos;

		String fname = this.getDefaultFileName();
		if (null == fname) {
			return false;
		}
		file = new File(path + "/" + fname);

		try {
			if (file.exists()) {
				file.delete();
			}
			file.createNewFile();

			dos = new DataOutputStream(new FileOutputStream(file));
			//
			// account.writeData(dos);
			data.writeData(dos);

			dos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if (file.exists() && file.isFile()) {
				file.delete();
			}

			return false;
		}
		return true;
	}

	synchronized public boolean writeDataToFile(FileOutputStream fos) {
		DataOutputStream dos;
		try {
			if (null == fos) {
				return false;
			}
			dos = new DataOutputStream(fos);
			//
			// account.writeData(dos);
			data.writeData(dos);

			dos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		return true;
	}

	synchronized public boolean readDataFromFile(String path) {
		File file;
		DataInputStream dis;
		try {
			String fname = this.getDefaultFileName();
			if (null == fname) {
				return false;
			}

			file = new File(path + "/" + fname);
			if (!file.exists()) {
				return false;
			}
			dis = new DataInputStream(new FileInputStream(file));
			//
			// account.readData(dis);
			data.readData(dis);

			dis.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			data = new DataManager();
			return false;
		}
		return true;

	}

	synchronized public boolean readDataFromFile(FileInputStream fis) {
		DataInputStream dis;
		try {
			if (null == fis) {
				return false;
			}
			dis = new DataInputStream(fis);
			//
			// account.readData(dis);
			data.readData(dis);

			dis.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			data = new DataManager();
			return false;
		}
		return true;

	}

	public String getDefaultFileName() {
		if (this.account.getUserid() != null) {
			return DESCrypto.encrypt(this.account.getUserid()) + "." + suffix;
		} else {
			return null;
		}
	}

}
